package com.mmg.spzx.manager.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mmg.spzx.common.exception.MmgException;
import com.mmg.spzx.manager.mapper.SysRoleUserMapper;
import com.mmg.spzx.manager.mapper.SysUserMapper;
import com.mmg.spzx.manager.service.SysUserService;
import com.mmg.spzx.model.dto.system.AssignRoleDto;
import com.mmg.spzx.model.dto.system.LoginDto;
import com.mmg.spzx.model.dto.system.SysUserDto;
import com.mmg.spzx.model.entity.system.SysUser;
import com.mmg.spzx.model.vo.common.ResultCodeEnum;
import com.mmg.spzx.model.vo.system.LoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private SysRoleUserMapper sysRoleUserMapper;

    @Override
    public LoginVo login(LoginDto loginDto) {

        // 校验验证码是否正确
        String captcha = loginDto.getCaptcha();     // 用户输入的验证码
        String codeKey = loginDto.getCodeKey();     // redis中验证码的数据key

        // 从Redis中获取验证码
        String redisCode = redisTemplate.opsForValue().get("user:login:validatecode:" + codeKey);
        if (StrUtil.isEmpty(redisCode) || !StrUtil.equalsIgnoreCase(redisCode, captcha)) {
            throw new MmgException(ResultCodeEnum.VALIDATECODE_ERROR);
        }

        // 验证通过删除redis中的验证码
        redisTemplate.delete("user:login:validatecode:" + codeKey);

        //获取用户名
        String userName = loginDto.getUserName();
        //根据用户名查询用户信息
        SysUser sysUser = sysUserMapper.selectUserByUserName(userName);
        //如果查不到，返回用户名不存在
        if (sysUser == null) {
            throw new MmgException(ResultCodeEnum.DATA_ERROR);
        }
        //存在，比较密码
        String password = DigestUtils.md5DigestAsHex(loginDto.getPassword().getBytes());
        String databasePassword = sysUser.getPassword();
        //密码不一致，返回密码错误
        if (!password.equals(databasePassword)) {
            throw new MmgException(ResultCodeEnum.LOGIN_ERROR);
        }
        //密码一致，返回token
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //把用户信息存入redis
        redisTemplate.opsForValue().set("user:login" + token, JSON.toJSONString(sysUser), 7, TimeUnit.DAYS);
        //返回结果
        LoginVo LoginVo = new LoginVo();
        LoginVo.setToken(token);
        return LoginVo;
    }

    @Override
    public SysUser getUserInfo(String token) {
        String json = redisTemplate.opsForValue().get("user:login" + token);
        if (StrUtil.isNotEmpty(json)) {
            return JSON.parseObject(json, SysUser.class);
        }
        return null;
    }

    @Override
    public void logout(String token) {
        redisTemplate.delete("user:login:" + token);
    }

    @Override
    public PageInfo<SysUser> findByPage(Integer pageNum, Integer pageSize, SysUserDto sysUserDto) {
        PageHelper.startPage(pageNum, pageSize);
        return new PageInfo<>(sysUserMapper.findByPage(sysUserDto));
    }

    @Override
    public void saveSysUser(SysUser sysUser) {
        //用户名唯一性校验
        SysUser user = sysUserMapper.selectUserByUserName(sysUser.getUserName());
        if (user != null) {
            throw new MmgException(ResultCodeEnum.DATA_ERROR);
        }
        //密码加密
        sysUser.setPassword(DigestUtils.md5DigestAsHex(sysUser.getPassword().getBytes()));
        sysUserMapper.saveSysUser(sysUser);
    }

    @Override
    public void updateSysUser(SysUser sysUser) {
        sysUserMapper.updateSysUser(sysUser);
    }

    @Override
    public void deleteById(Integer id) {
        sysUserMapper.deleteById(id);
    }

    @Override
    public void doAssign(AssignRoleDto assignRoleDto) {
        //根据用户id删除用户之前的分配过的角色数据，防止重复分配
        sysRoleUserMapper.deleteByUserId(assignRoleDto.getUserId());
        //重新分配角色
        List<Long> roleIdList = assignRoleDto.getRoleIdList();
        //roleIdList.stream().peek(roleId -> sysRoleUserMapper.doAssign(assignRoleDto.getUserId(), roleId));
        //批量插入
        sysRoleUserMapper.doAssign(assignRoleDto.getUserId(), roleIdList);
    }
}
